package org.erepublik.company.charts;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.erepublik.company.EAlliance;
import org.erepublik.company.ECountry;
import org.erepublik.company.Location;
import org.erepublik.company.service.JSONCountryDataProvider;
import org.erepublik.company.service.PriceIndexService;
import org.erepublik.company.service.XmlVatService;
import org.erepublik.company.utils.Utils;

public class ChartFactory {

    
    public static String getComparisonChart(long poczatekOkresu, ChartDataSet data, ChartDataSet data2, String title) {
        
        double minStat = 9999999;
        double maxStat = 0;

        ArrayList<ChartData> filteredData = prepareData(data, poczatekOkresu);
        ArrayList<ChartData> filteredData2 = prepareData(data2, poczatekOkresu);
        
        for (int i = 0; i < filteredData.size(); i++) {
            if (minStat > filteredData.get(i).getValue())
                minStat = filteredData.get(i).getValue();
            if (minStat > filteredData2.get(i).getValue())
                minStat = filteredData2.get(i).getValue();
        }
        for (int i = 0; i < filteredData.size(); i++) {
            if (maxStat < filteredData2.get(i).getValue())
                maxStat = filteredData2.get(i).getValue();
            if (maxStat < filteredData.get(i).getValue())
                maxStat = filteredData.get(i).getValue();
        }
        
        
        double diff = maxStat - minStat;
        long firstData = poczatekOkresu;
        long lastData = new Date().getTime();
        long timeLength = lastData - firstData;

        double[] x = new double[filteredData.size()];
        double[] x2 = new double[filteredData2.size()];
        int[] y = new int[filteredData.size()];
        int[] y2 = new int[filteredData2.size()];
        
        for (int i = 0; i < x.length; i++) {
            x[i] = Utils.round( (((filteredData.get(i).getTime() - firstData) / (double) timeLength) * 100.0) , 1);
            y[i] = (int) (((filteredData.get(i).getValue() - minStat) / diff) * 100);
        }

        for (int i = 0; i < x2.length; i++) {
            x2[i] = Utils.round( (((filteredData2.get(i).getTime() - firstData) / (double) timeLength) * 100.0) , 1);
            y2[i] = (int) (((filteredData2.get(i).getValue() - minStat) / diff) * 100);
        }       
        
        StringBuffer str = new StringBuffer("http://chart.apis.google.com/chart?");
        str.append("cht=lxy");
        str.append("&chd=t:");
        for (int i = 0; i < x.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(x[i]);
        }
        str.append("|");
        for (int i = 0; i < y.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(y[i]);
        }
        str.append("|");
        for (int i = 0; i < x2.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(x2[i]);
        }
        str.append("|");
        for (int i = 0; i < y2.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(y2[i]);
        }

        String[] xLabels = getLast7daysAsGoogleChart().toArray(new String[0]);

        str.append("&chs=600x300");
        str.append("&chco=FF0000,0000FF");
        str.append("&chxt=x,y");
        str.append("&chxr=1," + minStat + "," + maxStat + "," + (int) (diff / 5));
        str.append("&chxl=0:");
        for (int i = 0; i < 7; i++) {
            str.append("|");
            str.append(xLabels[i]);
        }

        str.append("&chf=c,lg,0,FFE7C6,0,76A4FB,1");
        str.append("&chtt=" + title);

        str.append("&chg=" + Utils.round(100.0d / (xLabels.length - 1), 2) + "," + 10);

        return str.toString();
        
        
        
    }
    
    
    
    public static String getSimpleChart(long poczatekOkresu, ChartDataSet data, String title) {

        double minStat = 9999999;
        double maxStat = 0;

        ArrayList<ChartData> filteredData = prepareData(data, poczatekOkresu);
        
        for (int i = 0; i < filteredData.size(); i++) {
            if (minStat > filteredData.get(i).getValue())
                minStat = filteredData.get(i).getValue();
        }
        for (int i = 0; i < filteredData.size(); i++) {

            if (maxStat < filteredData.get(i).getValue())
                maxStat = filteredData.get(i).getValue();
        }

        double diff = maxStat - minStat;
        long firstData = poczatekOkresu;
        long lastData = new Date().getTime();
        long timeLength = lastData - firstData;

        double[] x = new double[filteredData.size()];
        int[] y = new int[filteredData.size()];

        for (int i = 0; i < x.length; i++) {
            x[i] = Utils.round( (((filteredData.get(i).getTime() - firstData) / (double) timeLength) * 100.0d) , 1 );
            y[i] = (int) (((filteredData.get(i).getValue() - minStat) / diff) * 100);
        }

        StringBuffer str = new StringBuffer("http://chart.apis.google.com/chart?");
        str.append("cht=lxy");
        str.append("&chd=t:");
        for (int i = 0; i < x.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(x[i]);
        }
        str.append("|");
        for (int i = 0; i < y.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(y[i]);
        }

        String[] xLabels = getLast7daysAsGoogleChart().toArray(new String[0]);

        str.append("&chs=600x300");
        str.append("&chco=FF0000");
        str.append("&chxt=x,y");
        str.append("&chxr=1," + minStat + "," + maxStat + "," + (int) (diff / 5));
        str.append("&chxl=0:");
        for (int i = 0; i < 7; i++) {
            str.append("|");
            str.append(xLabels[i]);
        }

        str.append("&chf=c,lg,0,FFE7C6,0,76A4FB,1");
        str.append("&chtt=" + title);

        str.append("&chg=" + Utils.round(100.0d / (xLabels.length - 1), 2) + "," + 10);

        return str.toString();
    }

    
    
    
    private static ArrayList<ChartData> prepareData(ChartDataSet data, long poczatekOkresu) {

        smoothFilter(2, data);

        List<ChartData> filteredData = data.getData();

        ChartData[] sortedData = filteredData.toArray(new ChartData[0]);
        Arrays.sort(sortedData);
        filteredData = new ArrayList<ChartData>();
        for (ChartData chartData : sortedData) {
            filteredData.add(chartData);
        }

        ArrayList<ChartData> data2 = new ArrayList<ChartData>();
        for (ChartData chartData : filteredData) {
            if (chartData.getTime() > poczatekOkresu)
                data2.add(chartData);

        }
        filteredData = data2;

        return filterChart(filteredData, 1000*60*60); //2h
    }

    
    
    
    
    public static String getExchangeRateChart2Weeks(CountryJSONDataCollector collector, Location country) {
        ChartDataSet currencyPrice = collector.getData(country, ECountryDataType.CURRENCY_PRICE.toString());
        ChartDataSet goldPrice = collector.getData(country, ECountryDataType.GOLD_PRICE.toString());
        String title = "Average exchange rates of all currencies";
        if (country != null)
            title = country.getCurrencyName() + " exchange rate";

        return getEchangeRateChart(goldPrice, currencyPrice, new Date().getTime() - 1000 * 60 * 60 * 24 * 7, 50,
                getLast7daysAsGoogleChart().toArray(new String[0]), title);
    }

    public static String getExchangeRateChart2Months(CountryJSONDataCollector collector, ECountry country) {
        ChartDataSet currencyPrice = collector.getData(country, ECountryDataType.CURRENCY_PRICE.toString());
        ChartDataSet goldPrice = collector.getData(country, ECountryDataType.GOLD_PRICE.toString());
        String title = "Average exchange rates of all currencies";
        if (country != null)
            title = country.getCurrencyName() + " exchange rate";

        return getEchangeRateChart(goldPrice, currencyPrice, new Date().getTime() - 1000 * 60 * 60 * 24 * 28, 50,
                getLast2monthsAsGoogleChart().toArray(new String[0]), title);
    }

    private static String getEchangeRateChart(ChartDataSet goldPrice, ChartDataSet currencyPrice, long poczatekOkresu, int ilePunktopw,
            String[] xLabels, String title) {

        double minPrice = 999;
        double maxPrice = 0;

        List<ChartData> currencyData = currencyPrice.getData();
        ArrayList<ChartData> data2 = new ArrayList<ChartData>();
        for (ChartData chartData : currencyData) {
            if (chartData.getTime() > poczatekOkresu)
                data2.add(chartData);

        }
        currencyData = data2;

        List<ChartData> goldData = goldPrice.getData();
        ArrayList<ChartData> goldData2 = new ArrayList<ChartData>();
        for (ChartData chartData : goldData) {
            if (chartData.getTime() > poczatekOkresu)
                goldData2.add(chartData);

        }
        goldData = goldData2;

        for (int i = 0; i < currencyData.size(); i++) {
            if (minPrice > 1.0 / currencyData.get(i).getValue())
                minPrice = 1.0 / currencyData.get(i).getValue();
        }
        for (int i = 0; i < goldData.size(); i++) {

            if (maxPrice < goldData.get(i).getValue())
                maxPrice = goldData.get(i).getValue();
        }
        minPrice = ((int) (1000 * minPrice)) / 1000.0d;
        maxPrice += 0.001;
        double maxMin = maxPrice - minPrice;

        long firstData = poczatekOkresu;
        long lastData = new Date().getTime();
        long timeLength = lastData - firstData;

        int[] x = new int[currencyData.size()];
        int[] y = new int[currencyData.size()];
        int[] y2 = new int[currencyData.size()];
        for (int i = 0; i < x.length; i++) {
            x[i] = (int) (((currencyData.get(i).getTime() - firstData) / (double) timeLength) * 100);
            y[i] = (int) (((1.0 / currencyData.get(i).getValue() - minPrice) / maxMin) * 100);
            y2[i] = (int) (((goldData.get(i).getValue() - minPrice) / maxMin) * 100);
        }

        StringBuffer str = new StringBuffer("http://chart.apis.google.com/chart?");
        str.append("cht=lxy");
        str.append("&chd=t:");
        for (int i = 0; i < x.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(x[i]);
        }
        str.append("|");
        for (int i = 0; i < y.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(y[i]);
        }

        str.append("|");
        for (int i = 0; i < x.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(x[i]);
        }
        str.append("|");
        for (int i = 0; i < y2.length; i++) {
            if (i != 0)
                str.append(",");
            str.append(y2[i]);
        }

        str.append("&chs=600x300");
        str.append("&chco=FF0000,0000FF");
        str.append("&chxt=x,y,y");
        str.append("&chxr=1," + minPrice + "," + maxPrice + ",0.001|2," + 1 / minPrice + "," + 1 / maxPrice);
        str.append("&chxl=0:");
        for (int i = 0; i < 7; i++) {
            str.append("|");
            str.append(xLabels[i]);
        }
        str.append("|2:");
        for (double i = minPrice; i < maxPrice + 0.0001; i += 0.0005) {
            str.append("|");
            str.append(Utils.round(1.0 / i, 2));
        }

        str.append("&chf=c,lg,0,FFE7C6,0,76A4FB,1");
        str.append("&chtt=" + title);
        str.append("&chxs=1N*f3zsy*,0000DD,13,4,t|2N*f3zsy*,DD0000,13,2,t");

        str.append("&chg=" + Utils.round(100.0d / (xLabels.length - 1), 2) + "," + (1 / (maxMin * 10)));

        return str.toString();

    }

    @SuppressWarnings("deprecation")
    private static ArrayList<String> getLast7daysAsGoogleChart() {
        long today = new Date().getTime();
        ArrayList<String> dates = new ArrayList<String>();
        for (int i = 6; i >= 0; i--) {
            Date date = new Date(today - i * 1000l * 60l * 60l * 24l);
            dates.add(date.getDate() + "." + toRomanian(date.getMonth()));
        }

        return dates;
    }

    private static ArrayList<String> getLast2monthsAsGoogleChart() {
        ArrayList<String> dates = new ArrayList<String>();

        for (int i = 7; i >= 2; i--) {
            dates.add(i + "weeks ago");
        }
        dates.add("1 week ago");
        dates.add("now");
        return dates;
    }

    private static String toRomanian(int month) {
        if (month == 0)
            return "I";
        if (month == 1)
            return "II";
        if (month == 2)
            return "III";
        if (month == 3)
            return "IV";
        if (month == 4)
            return "V";
        if (month == 5)
            return "VI";
        if (month == 6)
            return "VII";
        if (month == 7)
            return "VIII";
        if (month == 8)
            return "IX";
        if (month == 9)
            return "X";
        if (month == 10)
            return "XI";
        if (month == 11)
            return "XII";

        return null;
    }

    public static void smoothFilter(int filterSize, ChartDataSet data) {
        List<ChartData> signal = data.getData();
        for (int i = filterSize; i < signal.size() - filterSize; i++) {
            double smoothedValue = 0;
            for (int j = i - filterSize; j <= i + filterSize; j++) {
                smoothedValue += signal.get(j).getValue() / (2 * filterSize + 1);
            }
            signal.get(i).setValue(smoothedValue);
        }
    }
    
    
    
    public static ArrayList<ChartData> filterChart(List<ChartData> data, long timeInMilisec) {
        
        ArrayList<ChartData> newData = new ArrayList<ChartData>();
        
        long time = Long.MIN_VALUE;
        
        for (ChartData chartData : data) {

            if (time + timeInMilisec < chartData.getTime()) {
                time = chartData.getTime();
                newData.add(chartData);
            }
        }

        return newData;
    }
    
    
    
    public static void main(String[] args) {
        
        CountryJSONDataCollector collector = new CountryJSONDataCollector(new XmlVatService());
        ChartDataSet eden = collector.getData(ECountry.POLAND, ECountryDataType.ONLINE.toString());
        ChartDataSet phoenix = collector.getData(ECountry.RUSSIA, ECountryDataType.ONLINE.toString());
        
        String chart = ChartFactory.getComparisonChart(new Date().getTime()-1000*60*60*24*7l, eden, phoenix, "bla");
        System.out.println(chart);
        
    }
    

}
